/**
 *   _                                                          _   
 *  | | ____ _ _ __ _ __ ___   __ _  ___           _ __ ___ ___| |_ 
 *  | |/ / _` | '__| '_ ` _ \ / _` |/ __|  _____  | '__/ _ | __| __|
 *  |   < (_| | |  | | | | | | (_| | (__  |_____| | | |  __|__ \ |_ 
 *  |_|\_\__,_|_|  |_| |_| |_|\__,_|\___|         |_|  \___|___/\__|
 *         
 *  Copyright  2011 Kondra, Inc. 
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at:
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package com.kondra.karmac.rest
{
   import flash.net.URLVariables;
   import flash.utils.Dictionary;

   [DefaultProperty( "services" )]
   
   /**
    * The <code>ServiceConfig</code> class is used to register service
    * endpoints, that requested by name in the application.
    * 
    * @author Jared Kaplan
    */
   public class ServiceConfig
   {
      private var m_serviceMap:Dictionary;
      
      public function ServiceConfig() {
         m_serviceMap = new Dictionary();   
      }
      
      /**
       * Loads a service configuration into the service manager.
       * 
       * @param config           Config data to load into the services manager
       */ 
      public function loadServicesConfig( config:XML ) : void
      {
         for each( var nextServiceGroup:XML in config..ServiceGroup )
         {
            var baseUrl:String = getNonEmptyConfigValue( nextServiceGroup.@baseUrl ); 

            for each( var nextServiceEndpoint:XML in nextServiceGroup..ServiceEndpoint )
            {
               var name:String = getNonEmptyConfigValue( nextServiceEndpoint.@name );

               if( name != null )
               {
                  var endpoint:ServiceEndpoint = new ServiceEndpoint();
                  
                  endpoint.name = name;
                  endpoint.baseUrl = baseUrl;
                  endpoint.url = getNonEmptyConfigValue( nextServiceEndpoint.@url );
                  endpoint.nocache = nextServiceEndpoint.@nocache == "true";
                  endpoint.method = getNonEmptyConfigValue( nextServiceEndpoint.@method );
                  endpoint.contentType = getNonEmptyConfigValue( nextServiceEndpoint.@contentType );
                  endpoint.resultFormat = getNonEmptyConfigValue( nextServiceEndpoint.@resultFormat );
                  endpoint.data = parseConfigDataValues( getNonEmptyConfigValue( nextServiceEndpoint.@data ) );
                  
                  registerService( name, endpoint );
               }
            }
         }
      }
      
      /**
       * Returns the specified string value or <code>null</code> if the the
       * value is an empty string.
       * 
       * @param value            The string value to return if not empty
       */ 
      private function getNonEmptyConfigValue( value:String ) : String {
         return value != null && value.length > 0 ? value : null;
      }
      
      /**
       * Returns data object specifed as URL variables.
       * 
       * @param data             Data values specified as URL variables
       */ 
      private function parseConfigDataValues( data:String ) : Object {
         return data != null ? new URLVariables( data ) : null;
      }
      
      /**
       * Returns a service endpoint that has been registered with this
       * service config object.
       * 
       * @param name The name of the service endpoint being requested
       */
      public function getService( name:String ) : IServiceEndpoint {
         return m_serviceMap[name] as IServiceEndpoint;
      }
      
      /**
       * Register a service endpoint with this service config.
       * 
       * @see ServiceEndpoint
       */ 
      public function registerService( name:String, service:IServiceEndpoint ) : void 
      {
         if( name != null )
            m_serviceMap[name] = service;
         else
            throw new Error( "ServiveConfig:registerService() : Name must be defined for a registered service!" );
      }
      
      //
      // getter/setter methods
      //
      [ArrayElementType("com.kondra.karmac.rest.IServiceEndpoint")]
      public function set services( services:Array ) : void
      {
         m_serviceMap = new Dictionary();
         
         for each( var next:IServiceEndpoint in services )
            registerService( next.getName(), next );
      }
   }
}